<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    
  </style>
</head>
<body>
  
</body>
<script>

  // function fn(){
    // this.sayHi = fn.prototype.sayHi;
  // }
  // fn.prototype.sayHi = function(){}

  // const o1 = new fn();
  // const o2 = new fn();
  // console.log(o1.sayHi === o2.sayHi);

  // 创建新对象
  // 改变this为该对象
  // 修改this的__proto__指向函数的prototype
  // 执行原函数
  // 返回对象
  

  // 原型的指向：修改this的__proto__指向函数的prototype

  // 隐式原型：所有的对象数据，都具有一个属性：__proto__，这个属性是对象类型
    // 用来指向创建自身的函数的prototype

  // const obj = {};
  // console.log(obj);

  // console.log(obj.[[Prototype]])

  // console.log(obj.__proto__)

  // 所有的对象都可以通过构造函数创建

  // const o = {};
  // console.log( o.__proto__ === Object.prototype );

  // function fn(){};
  // const f = new fn();
  // console.log( f.__proto__ === fn.prototype );

  // const str = "hello";
  // console.log( str.__proto__ === String.prototype );



  // 显式原型：所有的函数（除了箭头函数）都默认自带了一个属性：prototype
  // 用来被将来自身创建出的对象的__proto__指向，用来给将来创建出的对象做公共空间使用

  // 任何两个对象都不相等，只要相等了就是一个对象

  // Object.prototype.xxx = Symbol("hahaha");

  // const o1 = new Object();
  // const o2 = new Object();
  // const o3 = new Object();

  // console.log( o1.__proto__ === Object.prototype );

  // console.log(o1.__proto__.xxx)
  // console.log(o2.__proto__.xxx)
  // console.log(o3.__proto__.xxx)
  
  // console.log(o1.__proto__.xxx === o3.__proto__.xxx);



  // 隐式原型__proto__在使用时，可以省略

  // Object.prototype.xxx = Symbol("hahaha");

  // const o1 = new Object();
  // const o2 = new Object();
  // const o3 = new Object();

  // console.log( o1.__proto__ === Object.prototype );

  // console.log(o1.xxx)
  // console.log(o2.xxx)
  // console.log(o3.xxx)
  
  // console.log(o1.xxx === o3.xxx);


  // =======


  function fn(n){
    this.name = n;
    // this.aaa = "aaa1"
  }
  fn.prototype.aaa = "aaa2"
  fn.prototype.sayHello = function(){
    console.log("hello " + this.name)
  }

  const o1 = new fn("admin");

  o1.aaa = "hello";

  console.log(o1);
  o1.sayHello();


  const o2 = new fn("root");
  console.log(o2);
  o2.sayHello();

  console.log( o1.sayHello );
  console.log( o2.sayHello );
  console.log( o1.sayHello === o2.sayHello );

  console.log( o1.aaa );
  console.log( o2.aaa );

  // 原型链的规则：
    // 访问：
    // 对象在访问属性或方法时，会先在自身查找，找不到，会沿着__proto__依次查找，任意一层找到了，就使用，并停止查找，直到顶层Object.prototype，还没找到了，抛出undefined

    // 设置：
    // 对象在设置属性或方法时，直接设置到自身

  // console.log(o1.aaa)
</script>
</html>